package net.huashitong.controller.weChat;

import com.google.common.collect.Maps;
import huashitong.util.StringUtils;
import jodd.util.StringUtil;
import net.huashitong.config.ProjectConfig;
import net.huashitong.config.WebWeChatConfig;
import net.huashitong.entity.AccessToken;
import net.huashitong.entity.UserMessage;
import net.huashitong.entity.WeChatUserInfo;
import net.huashitong.formbean.RegisterFormBean;
import net.huashitong.service.user.SsUserLoginTokenService;
import net.huashitong.service.user.SsUserValidService;
import net.huashitong.service.user.UserService;
import net.huashitong.shiro.UsernamePasswordToken;
import net.huashitong.ssydt.security.entity.SsUserLoginToken;
import net.huashitong.ssydt.security.utils.Sha1Util;
import net.huashitong.ssydt.security.utils.UUIDGenerator;
import net.huashitong.user.results.User;
import net.huashitong.user.vo.ThirdRegisterInVO;
import net.huashitong.util.Message;
import net.huashitong.util.WebLoginUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static net.huashitong.util.WebLoginUtils.*;

/**
 * 微信公众号授权授权
 *
 * @author shaoxian.zhong
 */
@Controller
@RequestMapping("/wechat")
public class WebWeChatLoginController {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SsUserValidService ssUserValidService;
    @Autowired
    private SsUserLoginTokenService ssUserLoginTokenService;

    protected String getView(String view) {
        return String.format("/login/wechat/%s", view);
    }

    /**
     * 微信公众平台网页授权登录
     *
     * @param redirect_uri
     * @return
     */
    @RequestMapping("/login")
    public String login(@RequestParam String redirect_uri) {
        UserMessage userMessage = (UserMessage) SecurityUtils.getSubject().getPrincipal();
        if (userMessage != null) {
            SsUserLoginToken ssUserLoginToken = ssUserLoginTokenService.getByUserId(userMessage.getUserId());
            if (StringUtils.isNotBlank(ssUserLoginToken.getOpenId())) {
                User user = userService.get(userMessage.getUserId());
                if(user != null && StringUtils.isNotBlank(user.getMobile()) ){
                    return String.format("redirect:%s", redirect_uri);
                }
            }
        }
        String state = UUID.randomUUID().toString().trim().replaceAll("-", "");
        request.getSession().setAttribute("wechat:login:sign", state);
        request.getSession().setAttribute("wechat:login:url", redirect_uri);
        return "redirect:" + authorize(state);
    }

    /**
     * 用户同意授权后回调
     *
     * @param code
     * @param state
     * @return
     */
    @RequestMapping("/after")
    public String afterLogin(@RequestParam("code") String code, @RequestParam("state") String state) {
        String uuid = UUIDGenerator.uuid2();
        request.getSession().setAttribute("register", uuid);

        String sign = (String) request.getSession().getAttribute("wechat:login:sign");
        String url = (String) request.getSession().getAttribute("wechat:login:url");
        if (StringUtil.isBlank(sign) || !sign.equals(state)) {
            return "error/404";
        }
        Object obj = request.getSession().getAttribute("wechat:login:accessToken");
        AccessToken accessToken;
        if (obj != null) {
            accessToken = (AccessToken) obj;
        } else {
            accessToken = getAccessToken(code);
            if (accessToken.getErrcode() != null) {
//                logger.info("errcode:{},errmsg:{}", accessToken.getErrcode(), accessToken.getErrmsg());
                return "error/404";
            }
            request.getSession().setAttribute("wechat:login:accessToken", accessToken);
        }

        //根据Unionid取用户表，如果不为空执行登录，如果为空跳转绑定手机号页面
        if (StringUtils.isNotBlank(accessToken.getUnionid())) {
            String userId = userService.getByThirdAccountWithToken("WeChat", accessToken.getUnionid());
            if (StringUtils.isBlank(userId)) {

                request.getSession().setAttribute("wechat:login:accessToken", accessToken);
                return "user/bind";
            } else {
                User user = userService.get(userId);
                if(user == null || StringUtils.isBlank(user.getMobile()) ){
                    request.getSession().setAttribute("wechat:login:accessToken", accessToken);
                    return "user/bind";
                }

                //写入token
                SsUserLoginToken ssUserLoginToken = ssUserLoginTokenService.login(userId);

                //记录OpenId
                if (ssUserLoginToken != null ) {
                    if(!accessToken.getOpenid().equals(ssUserLoginToken.getOpenId())) {
                        ssUserLoginToken.setOpenId(accessToken.getOpenid());
                        ssUserLoginTokenService.update(ssUserLoginToken);
                    }
                }

                //执行登录
                UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(accessToken.getUnionid(), "123456".toCharArray(),
                        false, "WeChat", request, "");
                try {
                    SecurityUtils.getSubject().login(usernamePasswordToken);
                } catch (UnknownAccountException uae) {
                    // error = "帐号或密码错误";
                } catch (IncorrectCredentialsException ice) {
                    // error = "密码不正确";
                } catch (LockedAccountException lae) {
                    // error = "帐号被锁定";
                } catch (ExcessiveAttemptsException eae) {
                    // error = "有人尝试登录您的帐号超过五次, 系统自动开启了保护模式, 请十分钟后再试";
                } catch (AuthenticationException ae) {
                    // error = "未知错误";
                }
            }
        } else {
            return "error/404";
        }
//        UserMessage userMessage =(UserMessage)SecurityUtils.getSubject().getPrincipal();
        return String.format("redirect:%s", url);
    }

    /**
     * 执行绑定手机流程
     *
     * @return
     */
    @RequestMapping(value = "/binding/after", method = RequestMethod.POST)
    public String binding(@ModelAttribute RegisterFormBean registerDatabean, Model model) {
        String error;
        if (StringUtils.isBlank(registerDatabean.getMobile()) || StringUtils.isBlank(registerDatabean.getVaildCode())) {
            error = "手机号或者验证码不能为空";
            model.addAttribute("registerDatabean", registerDatabean);
            model.addAttribute("error", error);
            return "user/bind";
        }
        String url = (String) request.getSession().getAttribute("wechat:login:url");
        Object obj = request.getSession().getAttribute("wechat:login:accessToken");

        AccessToken accessToken;
        String mobile = registerDatabean.getMobile();
        if (obj != null) {
            accessToken = (AccessToken) obj;
        } else {
            error = "非法操作";
            model.addAttribute("registerDatabean", registerDatabean);
            model.addAttribute("error", error);
            return "user/bind";
        }
        //验证码校验
        if (ssUserValidService.isPast5MinOrErr(mobile, registerDatabean.getVaildCode())) {
            error = "验证码错误";
            model.addAttribute("registerDatabean", registerDatabean);
            model.addAttribute("error", error);
            return "user/bind";
        }
        //微信注册
        WeChatUserInfo weChatUserInfo = getUserInfo(accessToken.getAccess_token(), accessToken.getOpenid());
        if (StringUtil.isBlank(weChatUserInfo.getUnionid())) {
            weChatUserInfo.setUnionid(accessToken.getUnionid());
        }
        ThirdRegisterInVO thirdRegisterInVO = getThirdRegisterInVO4WeChat(weChatUserInfo, registerDatabean.getMobile());
        try {
            userService.thirdRegister(thirdRegisterInVO);
        } catch (UnknownAccountException uae) {
            // error = "帐号或密码错误";
        }

        //5.执行登录
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(accessToken.getUnionid(), "123456".toCharArray(),
                false, "WeChat", request, mobile);
        try {
            SecurityUtils.getSubject().login(usernamePasswordToken);
        } catch (UnknownAccountException uae) {
            // error = "帐号或密码错误";
        } catch (IncorrectCredentialsException ice) {
            // error = "密码不正确";
        } catch (LockedAccountException lae) {
            // error = "帐号被锁定";
        } catch (ExcessiveAttemptsException eae) {
            // error = "有人尝试登录您的帐号超过五次, 系统自动开启了保护模式, 请十分钟后再试";
        } catch (AuthenticationException ae) {
            // error = "未知错误";
        }
        return String.format("redirect:%s", url);
    }

    private ThirdRegisterInVO getThirdRegisterInVO4WeChat(WeChatUserInfo weChatUserInfo, String mobile) {
        ThirdRegisterInVO vo = new ThirdRegisterInVO();
        vo.setThirdAccount("WeChat");
        vo.setToken(weChatUserInfo.getUnionid());
        vo.setMobile(mobile);
        vo.setTerminal("Browser");
        vo.setProductSource(ProjectConfig.PRODUCT_CODE);
        vo.setNickname(weChatUserInfo.getNickname());
        vo.setImageUrl(weChatUserInfo.getHeadimgurl());
        return vo;
    }

    /**
     * 获取签名-jsSDK
     *
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/getJsSign", method = RequestMethod.POST)
    public Message getJsSign(@RequestParam String url) {

        //获取accessToken
        String tokenKeys = "wechat:login:accessToken";
        String access_Token = stringRedisTemplate.opsForValue().get(tokenKeys);
        if (StringUtil.isBlank(access_Token)) {
            try {
                stringRedisTemplate.opsForValue().set(tokenKeys, access_Token, 7000, TimeUnit.MINUTES);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //获取jsapi_ticket
        String ticketKeys = "wechat:ticket";
        String ticket = stringRedisTemplate.opsForValue().get(ticketKeys);
        if (StringUtil.isBlank(ticket)) {
            ticket = String.valueOf(WebLoginUtils.getJsapi_ticket(access_Token).get("ticket"));
            try {
                stringRedisTemplate.opsForValue().set(ticketKeys, ticket, 7000, TimeUnit.MINUTES);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        //获取签名
        String sign;
        String noncestr = Sha1Util.getNonceStr();
        String timestamp = Sha1Util.getTimeStamp();
        try {
            sign = WebLoginUtils.getJsapi_sign(ticket, url, noncestr, timestamp);
        } catch (Exception e) {
            return new Message("500", e.getMessage());
        }

        Map<String, Object> map = Maps.newHashMap();
        map.put("appid", WebWeChatConfig.APPID);
        map.put("noncestr", noncestr);
        map.put("timestamp", timestamp);
        map.put("sign", sign);

        return new Message("200", "", map);
    }

    /**
     * 获取url-分享
     *
     * @return
     * @throws Exception
     */
    @RequestMapping("/share/getUrl")
    public String getUrl() {

        return "/app/wechat/qun";
    }


}